﻿////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  © 2012 Stanislav S. Yarmonov.
//
//  TODO:LICENSE
//     
////////////////////////////////////////////////////////////////////////////////////////////////////
using System;

namespace Pandora.Development.Parser
{
    public static class IParseResultsExtensions
    {
        public static bool IsFailure<TToken, TResult>(this IParseResults<TToken, TResult> results)
        {
            return results is IParseFailure<TToken, TResult>;
        }

        public static bool IsSuccess<TToken, TResult>(this IParseResults<TToken, TResult> results)
        {
            return results is IParseSuccess<TToken, TResult>;
        }

        public static IParseFailure<TToken, TResult> AsFailure<TToken, TResult>(this IParseResults<TToken, TResult> results)
        {
            return results as IParseFailure<TToken, TResult>;
        }

        public static IParseSuccess<TToken, TResult> AsSuccess<TToken, TResult>(this IParseResults<TToken, TResult> results)
        {
            return results as IParseSuccess<TToken, TResult>;
        }

        public static IParseResults<TToken, TResult> OnSuccess<TToken, TResult>(this IParseResults<TToken, TResult> results, Action<IParseSuccess<TToken, TResult>> action)
        {
            IParseSuccess<TToken, TResult> success = results.AsSuccess<TToken, TResult>();
            if (success != null)
            {
                action(success);
            }

            return results;
        }

        public static IParseResults<TToken, TResult> OnFailure<TToken, TResult>(this IParseResults<TToken, TResult> results, Action<IParseFailure<TToken, TResult>> action)
        {
            IParseFailure<TToken, TResult> failure = results.AsFailure();
            if (failure != null)
            {
                action(failure);
            }

            return results;
        }

        public static IParseResults<TToken, TResult> If<TToken, TInput, TResult>(
            this IParseResults<TToken, TInput> results,
            Func<IParseSuccess<TToken, TInput>, IParseResults<TToken, TResult>> onSuccess,
            Func<IParseFailure<TToken, TInput>, IParseResults<TToken, TResult>> onFailure
        )
        {
            IParseSuccess<TToken, TInput> success = results.AsSuccess();
            if (success != null)
            {
                return onSuccess(success);
            }

            IParseFailure<TToken, TInput> failure = results.AsFailure();
            if (failure != null)
            {
                return onFailure(failure);
            }

            throw new Exception(); //TODO:
        }

        public static IParseResults<TToken, TResult> If<TToken, TResult>(
            this IParseResults<TToken, TResult> results,
            Func<IParseSuccess<TToken, TResult>, IParseResults<TToken, TResult>> onSuccess,
            Func<IParseFailure<TToken, TResult>, IParseResults<TToken, TResult>> onFailure
        )
        {
            return results.If<TToken, TResult, TResult>(onSuccess, onFailure);
        }
    }
}
